//
//  ADWebViewController.swift
//  ADKit
//
//  Created by Adoma on 2020/11/12.
//

import UIKit
import WebKit
import RxSwift
import RxCocoa
import SnapKit

open class ADWebViewController: UIViewController {
    
    struct Layout {
        static let controlViewHeight: CGFloat = 44 + kSafeAreaBottom
    }
    
    public private(set) var webView: WKWebView!
    public private(set) var url: URL?
    
    private var html: String?
    private var disposeBag = DisposeBag()
    
    public init(url: URL?) {
        self.url = url
        super.init(nibName: nil, bundle: nil)
    }
    
    public init(html: String?) {
        self.html = html
        super.init(nibName: nil, bundle: nil)
    }
    
    required public init?(coder: NSCoder) {
        super.init(coder: coder)
    }
    
    public let progressIndicator = ADProgress()
    public let titleSubject = PublishSubject<String?>()
    
    let controlView = PageControlView()
    var controlViewHeightConstraint: Constraint?
    
    public var showControlView = true {
        didSet {
            controlView.isHidden = showControlView == false
        }
    }
    
    var needControlView = false {
        didSet {
            if oldValue == needControlView {
                return
            }
            var offset: CGFloat = 1
            if needControlView {
                offset = 0
                webView.scrollView.contentInset.bottom = 0
            } else {
                webView.scrollView.contentInset.bottom = kSafeAreaBottom
            }
            controlViewHeightConstraint?.update(offset: offset * Layout.controlViewHeight)
        }
    }
    
    deinit {
        webView?.stopLoading()
    }
    
    override open func viewDidLoad() {
        super.viewDidLoad()
        
        view.backgroundColor = .white
        
        configWebView()
        view.addSubview(webView)
        
        configControlView()
        view.addSubview(controlView)
        
        view.addSubview(progressIndicator)
        progressIndicator.snp.makeConstraints { (make) in
            make.top.equalTo(self.view.snp.topMargin)
            make.left.right.equalToSuperview()
            make.height.equalTo(2)
        }
        
        webView.snp.makeConstraints { (make) in
            make.top.equalTo(progressIndicator)
            make.left.right.equalToSuperview()
        }
        
        controlView.snp.makeConstraints { (make) in
            make.top.equalTo(webView.snp.bottom)
            make.left.right.equalToSuperview()
            make.height.equalTo(Layout.controlViewHeight)
            self.controlViewHeightConstraint = make.bottom.equalToSuperview().offset(Layout.controlViewHeight).constraint
        }
        
        if let url = url {
            load(url)
        } else if let html = html {
            webView.loadHTMLString(html, baseURL: nil)
        }
    }
    
    open func load(_ url: URL) {
        webView.load(URLRequest.init(url: url))
    }
    
    open func customConfiguration(userContent: WKUserContentController) {}
    
    func configWebView() {
        
        let userContentController = WKUserContentController()
        customConfiguration(userContent: userContentController)

        /// vConsole
        if APPManager.shared.isTest,
           let data = NSDataAsset(name: "vconsole", bundle: .for(name: "ADKit"))?.data,
           let source = String(data: data, encoding: .utf8) {
            let vConsoleScript = WKUserScript(source: source, injectionTime: .atDocumentEnd, forMainFrameOnly: false)
            userContentController.addUserScript(vConsoleScript)
            
            let loadVConsoleScript = WKUserScript(source: "new window.VConsole();", injectionTime: .atDocumentEnd, forMainFrameOnly: false)
            userContentController.addUserScript(loadVConsoleScript)
        }
        
        let configuration = WKWebViewConfiguration()
        configuration.allowsInlineMediaPlayback = true
        configuration.userContentController = userContentController
        
        webView = WKWebView.init(frame: .zero, configuration: configuration)
                
        if #available(iOS 11.0, *) {
            webView.scrollView.contentInsetAdjustmentBehavior = .never
        } else {
            // Fallback on earlier versions
        }
        webView.scrollView.contentInset.bottom = kSafeAreaBottom
        
        webView.rx.observeWeakly(Double.self, "estimatedProgress")
            .distinctUntilChanged()
            .asDriver(onErrorJustReturn: 0)
            .drive(onNext: {[weak self] progress in
                self?.progressIndicator.progress = progress ?? 0
            })
            .disposed(by: disposeBag)
        
        webView.rx.observeWeakly(String.self, "title")
            .distinctUntilChanged()
            .asDriver(onErrorJustReturn: nil)
            .drive(titleSubject)
            .disposed(by: rx.disposeBag)

    }
    
    func configControlView() {
        
        let canGoBack = webView.rx.observeWeakly(Bool.self, "canGoBack").asObservable()
        let canGoForward = webView.rx.observeWeakly(Bool.self, "canGoForward").asObservable()
        
        Observable.combineLatest(canGoBack, canGoForward).subscribe(onNext: {[weak self] (arg) in
            if self?.showControlView == false {
                return
            }
            if arg.0 == false && arg.1 == false {
                self?.needControlView = false
            } else {
                self?.needControlView = true
            }
        }).disposed(by: disposeBag)
        
        canGoBack.map { can -> Bool in
            return can ?? false
        }.bind(to: controlView.backButton.rx.isEnabled).disposed(by: disposeBag)
        
        canGoForward.map { can -> Bool in
            return can ?? false
        }.bind(to: controlView.forwardButton.rx.isEnabled).disposed(by: disposeBag)
        
        controlView.backButton.rx.tap.subscribe(onNext: { [weak self] _ in
            guard let self = self else { return }
            self.webView.goBack()
        }).disposed(by: disposeBag)
        
        controlView.forwardButton.rx.tap.subscribe(onNext: { [weak self] _ in
            guard let self = self else { return }
            self.webView.goForward()
        }).disposed(by: disposeBag)
    }
    
}

class PageControlView: UIView {
    
    lazy var backButton: UIButton = {
        let btn = UIButton()
        btn.setImage(UIImage(name: "web_view_back", bundle: .for(name: "ADKit")), for: .normal)
        btn.setTitleColor(.black, for: .normal)
        return btn
    }()
    
    lazy var forwardButton: UIButton = {
        let btn = UIButton()
        btn.setImage(UIImage(name: "web_view_forward", bundle: .for(name: "ADKit")), for: .normal)
        btn.setTitleColor(.black, for: .normal)
        return btn
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        initUI()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func initUI() {
        
        addSubview(backButton)
        addSubview(forwardButton)
        
        backButton.snp.makeConstraints { (make) in
            make.right.equalTo(self.snp.centerX).offset(-15)
            make.top.equalToSuperview()
            make.width.equalTo(60)
            make.height.equalTo(44)
        }
        
        forwardButton.snp.makeConstraints { (make) in
            make.left.equalTo(self.snp.centerX).offset(15)
            make.centerY.height.width.equalTo(backButton)
        }
    }
    
}

